/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.testis.gui.mvc.controller.testbed;

import org.testis.gui.mvc.controller.AbstractController;
import org.testis.utils.tree.TbedMutableTreeNode;
import org.testis.gui.mvc.model.testbed.TbedTreeModel;
import org.testis.orm.testbed.refined.DeviceDefinitionFactory;
import org.testis.orm.testbed.refined.DeviceDefinitionRefined;
import org.testis.orm.testbed.refined.DeviceFirmwareRefined;
import org.testis.orm.testbed.refined.DeviceGroupDetailRefined;
import org.testis.orm.testbed.refined.DeviceGroupFactory;
import org.testis.orm.testbed.refined.DeviceGroupRefined;
import org.testis.orm.testbed.refined.DirectSerialConfigFactory;
import org.testis.orm.testbed.refined.DirectSerialConfigRefined;
import org.testis.orm.testbed.refined.DutRefined;
import org.testis.orm.testbed.refined.NetworkAdapterRefined;
import org.testis.orm.testbed.refined.NetworkSerialConfigFactory;
import org.testis.orm.testbed.refined.NetworkSerialConfigRefined;
import org.testis.orm.testbed.refined.SerialConfigBase;
import org.testis.orm.testbed.refined.SerialConnectionRefined;
import org.testis.orm.testbed.refined.TestBedItem;
import org.testis.orm.testbed.refined.TestPcFactory;
import org.testis.orm.testbed.refined.TestPcRefined;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.swing.tree.TreePath;

/**
 *
 * @author selcuk
 */
public class TbedTreeController extends AbstractController {

    public static final String SHOW_VIEW_PROPERTY = "ViewVisibility";
    public static final String TREE_LOAD_PROPERTY = "LoadTree";
    public static final String TREE_REFRESH_PROPERTY = "RefreshTree";
    public static final String SELECTED_NODE_PROPERTY = "SelectedNode";
    public static final String SELECTION_TREE_PATH_PROPERTY = "SelectionTreePath";
    public static final String ERROR_PROPERTY = "LastError";
    public static final String DEVICES_NODE_NAME = "Devices";
    public static final String DEVICE_GROUP_NODE_NAME = "Device Group";
    public static final String TEST_PC_NODE_NAME = "Test PCs";
    public static final String SERIAL_CONN_NODE_NAME = "Serial Connections";
    private TbedMutableTreeNode m_tbedTreeRoot;

    public TbedTreeController() {
        super();
        initialize();
    }

    synchronized public void operationLoadTree(TbedMutableTreeNode treeNode) {
        setModelProperty(TREE_LOAD_PROPERTY, treeNode);
    }

    public void operationSelectTreePath(TreePath path) {
        if (path != null) {
            setModelProperty(SELECTION_TREE_PATH_PROPERTY, path);
            operationSelectTestBedItem(
                    (TbedMutableTreeNode) path.getLastPathComponent());
        }
    }

    public void operationRefreshTree() {
        setModelProperty(TREE_REFRESH_PROPERTY, true);
    }

    public void startLoader() {
        initialize();
        setModelProperty(SHOW_VIEW_PROPERTY, true);
    }

    private void initialize() {
        addModel(new TbedTreeModel());
        loadTbedTree();
    }

    private void loadTbedTree() {
        TbedMutableTreeNode root = getTbedTreeRoot();

        TbedMutableTreeNode devicesNode = getDevicesNode();
        root.add(devicesNode);

        TbedMutableTreeNode testPCsNode = getTestPCsNode();
        root.add(testPCsNode);

        TbedMutableTreeNode deviceGroupNode = getDeviceGroupNode();
        root.add(deviceGroupNode);

        TbedMutableTreeNode connGroupNode = getSerialConnectionNode();
        root.add(connGroupNode);
    }

    private TbedMutableTreeNode getDevicesNode() {
        TbedMutableTreeNode root = new TbedMutableTreeNode("Devices");
        List<DeviceDefinitionRefined> deviceList = DeviceDefinitionFactory.newInstance().getDeviceList();
        for (Iterator<DeviceDefinitionRefined> it = deviceList.iterator(); it.hasNext();) {
            DeviceDefinitionRefined device = it.next();
            TbedMutableTreeNode deviceNode = new TbedMutableTreeNode(device);

            List<DeviceFirmwareRefined> fwList = device.getFirmwareList();
            Collections.sort(fwList);
            for (Iterator<DeviceFirmwareRefined> it1 = fwList.iterator(); it1.hasNext();) {
                DeviceFirmwareRefined fwRefined = it1.next();
                TbedMutableTreeNode fwNode = new TbedMutableTreeNode(fwRefined);
                deviceNode.add(fwNode);
            }
            root.add(deviceNode);
        }
        return root;
    }

    private TbedMutableTreeNode getTestPCsNode() {
        TbedMutableTreeNode root = new TbedMutableTreeNode("Test PCs");
        List<TestPcRefined> testPcList = TestPcFactory.newInstance().getTestPcList();
        Collections.sort(testPcList);
        for (Iterator<TestPcRefined> it = testPcList.iterator(); it.hasNext();) {
            TestPcRefined testPC = it.next();
            TbedMutableTreeNode testPcNode = new TbedMutableTreeNode(testPC);

            TbedMutableTreeNode dutsNode = new TbedMutableTreeNode("DUTs");
            testPcNode.add(dutsNode);
            List<DutRefined> dutList = testPC.getDutList();
            Collections.sort(dutList);
            for (Iterator<DutRefined> it1 = dutList.iterator(); it1.hasNext();) {
                DutRefined dutRefined = it1.next();
                TbedMutableTreeNode fwNode = new TbedMutableTreeNode(dutRefined);
                dutsNode.add(fwNode);
            }

            TbedMutableTreeNode adaptersNode = new TbedMutableTreeNode(
                    "Network Adapters");
            testPcNode.add(adaptersNode);
            List<NetworkAdapterRefined> adapterList = testPC.getNetworkAdapterList();
            Collections.sort(adapterList);
            for (Iterator<NetworkAdapterRefined> it1 = adapterList.iterator(); it1.hasNext();) {
                NetworkAdapterRefined adapterRefined = it1.next();
                TbedMutableTreeNode node = new TbedMutableTreeNode(
                        adapterRefined);
                adaptersNode.add(node);
            }
            root.add(testPcNode);
        }
        return root;
    }

    private TbedMutableTreeNode getDeviceGroupNode() {
        TbedMutableTreeNode root = new TbedMutableTreeNode("Device Group");
        List<DeviceGroupRefined> groups = DeviceGroupFactory.newInstance().getDeviceGroupList();
        Collections.sort(groups);
        for (Iterator<DeviceGroupRefined> it = groups.iterator(); it.hasNext();) {
            DeviceGroupRefined deviceGroup = it.next();
            TbedMutableTreeNode deviceGroupNode = new TbedMutableTreeNode(
                    deviceGroup);
            List<DeviceGroupDetailRefined> detailList = deviceGroup.getDetailList();
            Collections.sort(detailList);
            for (Iterator<DeviceGroupDetailRefined> it1 = detailList.iterator(); it1.hasNext();) {
                TbedMutableTreeNode detailNode = new TbedMutableTreeNode(
                        it1.next());
                deviceGroupNode.add(detailNode);
            }
            root.add(deviceGroupNode);
        }
        return root;
    }

    private TbedMutableTreeNode getSerialConnectionNode() {
        TbedMutableTreeNode root = new TbedMutableTreeNode("Serial Connections");

        TbedMutableTreeNode directRootNode = new TbedMutableTreeNode("Direct");
        List<DirectSerialConfigRefined> directConfigList = DirectSerialConfigFactory.newInstance().getConfigList();
        for (Iterator<DirectSerialConfigRefined> it = directConfigList.iterator(); it.hasNext();) {
            DirectSerialConfigRefined directSerial = (DirectSerialConfigRefined) it.next();
            TbedMutableTreeNode directSerialNode = new TbedMutableTreeNode(
                    directSerial);

            List<SerialConnectionRefined> children = directSerial.getSerialConnections();
            for (Iterator<SerialConnectionRefined> it1 = children.iterator(); it1.hasNext();) {
                directSerialNode.add(new TbedMutableTreeNode(it1.next()));
            }
            directRootNode.add(directSerialNode);
        }
        root.add(directRootNode);

        TbedMutableTreeNode networkRootNode = new TbedMutableTreeNode("Network");
        List<NetworkSerialConfigRefined> networkConfigList = NetworkSerialConfigFactory.newInstance().getConfigList();
        for (Iterator<NetworkSerialConfigRefined> it = networkConfigList.iterator(); it.hasNext();) {
            NetworkSerialConfigRefined networkSerial = (NetworkSerialConfigRefined) it.next();
            TbedMutableTreeNode networkSerialNode = new TbedMutableTreeNode(
                    networkSerial);

            List<SerialConnectionRefined> children = networkSerial.getSerialConnections();
            for (Iterator<SerialConnectionRefined> it1 = children.iterator(); it1.hasNext();) {
                networkSerialNode.add(new TbedMutableTreeNode(it1.next()));
            }
            networkRootNode.add(networkSerialNode);
        }
        root.add(networkRootNode);

//        List<SerialConnectionRefined> connections = SerialConnectionFactory.newInstance().getConnectionList();
//        for (Iterator<SerialConnectionRefined> it = connections.iterator(); it.hasNext();) {
//            SerialConnectionRefined refined = it.next();
//            TbedMutableTreeNode connectionNode = new TbedMutableTreeNode(refined);
//            root.add(connectionNode);
//        }
        return root;
    }

    public TestBedItem getSelectedTestBedItem() {
        TbedMutableTreeNode selectedNode = getSelectedTreeNode();
        if (selectedNode != null) {
            if (selectedNode.getUserObject() != null && selectedNode.getUserObject() instanceof TestBedItem) {
                return (TestBedItem) selectedNode.getUserObject();
            }
        }
        return null;
    }

    public TbedMutableTreeNode getSelectedTreeNode() {
        return (TbedMutableTreeNode) getModelProperty(SELECTED_NODE_PROPERTY);
    }

    private void setSelectedTreeNode(TbedMutableTreeNode node) {
        setModelProperty(SELECTED_NODE_PROPERTY, node);
    }

    synchronized public void operationSelectTestBedItem(TbedMutableTreeNode node) {
        setSelectedTreeNode(node);
    }

    public void operationCloseWindow() {
        super.cleanAll();
    }

    public void operationAddTestBedItem(TestBedItem newTBedItem) {
        TbedMutableTreeNode parentTreeNode = getSelectedTreeNode();
//        TestBedItem parentTBedItem = getSelectedTestBedItem();
        TbedMutableTreeNode newNode = new TbedMutableTreeNode(newTBedItem);

        if (newTBedItem instanceof TestPcRefined) {
            newNode.add(new TbedMutableTreeNode("DUTs"));
            newNode.add(new TbedMutableTreeNode("Network Adapters"));
        } else if (newTBedItem instanceof SerialConfigBase) {
            if (newTBedItem instanceof DirectSerialConfigRefined) {
                parentTreeNode = (TbedMutableTreeNode) parentTreeNode.getChildAt(
                        0);
            } else if (newTBedItem instanceof NetworkSerialConfigRefined) {
                parentTreeNode = (TbedMutableTreeNode) parentTreeNode.getChildAt(
                        1);
            }
        } else if (newTBedItem instanceof DutRefined) {
            // TEST PC altında DUTs
            parentTreeNode = (TbedMutableTreeNode) parentTreeNode.getChildAt(
                    0);
        } else if (newTBedItem instanceof NetworkAdapterRefined) {
            // TEST PC altında Adapters
            parentTreeNode = (TbedMutableTreeNode) parentTreeNode.getChildAt(
                    1);
        }
        parentTreeNode.add(newNode);
        operationRefreshTree();
        operationSelectTreePath(new TreePath(newNode.getPath()));
    }

    public void operationRemoveSelectedTestBedItem() {
        TbedMutableTreeNode selectedTreeNode = getSelectedTreeNode();
        selectedTreeNode.removeFromParent();
        operationRefreshTree();
    }

    public void operationSetErrorProperty(String msg) {
        setModelProperty(ERROR_PROPERTY, msg);
    }

    public TbedMutableTreeNode getTbedTreeRoot() {
        if (m_tbedTreeRoot == null) {
            setTbedTreeRoot(new TbedMutableTreeNode("ROOT"));
        }
        return m_tbedTreeRoot;
    }

    public void setTbedTreeRoot(TbedMutableTreeNode rootNode) {
        m_tbedTreeRoot = rootNode;
    }

    void operationMoveSelectedTestBedItem(int moveToParentId) {
        TestBedItem _testbedItem = getSelectedTestBedItem();
        TbedMutableTreeNode moveToNode = null;
        if (_testbedItem != null) {
            if (_testbedItem instanceof DeviceFirmwareRefined) {
                moveToNode = getDeviceDefinitionTreeNode(moveToParentId);
            } else if (_testbedItem instanceof DutRefined) {
                moveToNode = getTestPcTreeNode(moveToParentId);
            } else if (_testbedItem instanceof NetworkAdapterRefined) {
                moveToNode = getTestPcTreeNode(moveToParentId);
            } else if (_testbedItem instanceof DeviceGroupDetailRefined) {
                moveToNode = getDeviceGroupTreeNode(moveToParentId);
            }
        }

        if (moveToNode != null) {
            operationRemoveSelectedTestBedItem();
            operationSelectTestBedItem(moveToNode);
            operationAddTestBedItem(_testbedItem);
        }
    }

    private TbedMutableTreeNode getDeviceDefinitionTreeNode(int deviceId) {
        TbedMutableTreeNode result = null;
        TbedMutableTreeNode devicesNode = (TbedMutableTreeNode) m_tbedTreeRoot.getChildAt(
                0);
        if (devicesNode == null) {
            return result;
        }

        for (int i = 0; i < devicesNode.getChildCount(); i++) {
            TbedMutableTreeNode childNode = (TbedMutableTreeNode) devicesNode.getChildAt(
                    i);
            if (childNode == null) {
                continue;
            }
            if (childNode.getUserObject() != null && childNode.getUserObject() instanceof DeviceDefinitionRefined) {
                DeviceDefinitionRefined device = (DeviceDefinitionRefined) childNode.getUserObject();
                if (device.getId() == deviceId) {
                    result = childNode;
                    break;
                }
            }
        }
        return result;
    }

    private TbedMutableTreeNode getTestPcTreeNode(int testPcId) {
        TbedMutableTreeNode result = null;
        TbedMutableTreeNode testPCsNode = (TbedMutableTreeNode) m_tbedTreeRoot.getChildAt(
                1);
        if (testPCsNode == null) {
            return result;
        }

        for (int i = 0; i < testPCsNode.getChildCount(); i++) {
            TbedMutableTreeNode childNode = (TbedMutableTreeNode) testPCsNode.getChildAt(
                    i);
            if (childNode == null) {
                continue;
            }

            if (childNode.getUserObject() != null && childNode.getUserObject() instanceof TestPcRefined) {
                TestPcRefined device = (TestPcRefined) childNode.getUserObject();
                if (device.getId() == testPcId) {
                    result = childNode;
                    break;
                }
            }
        }
        return result;
    }

    private TbedMutableTreeNode getDeviceGroupTreeNode(int groupId) {
        TbedMutableTreeNode result = null;
        TbedMutableTreeNode groupsNode = (TbedMutableTreeNode) m_tbedTreeRoot.getChildAt(
                2);
        if (groupsNode == null) {
            return result;
        }

        for (int i = 0; i < groupsNode.getChildCount(); i++) {
            TbedMutableTreeNode childNode = (TbedMutableTreeNode) groupsNode.getChildAt(
                    i);
            if (childNode == null) {
                continue;
            }

            if (childNode.getUserObject() != null && childNode.getUserObject() instanceof DeviceGroupRefined) {
                DeviceGroupRefined group = (DeviceGroupRefined) childNode.getUserObject();
                if (group.getId() == groupId) {
                    result = childNode;
                    break;
                }
            }
        }
        return result;
    }
}
